Imports System.Collections.Generic
Imports System.Management

#Region "Structures"
''' <summary>
''' Computer memory information.
''' </summary>
''' <remarks></remarks>
Public Structure ComputerMemory
  Private _availablePhysicalMemory As Long
  ''' <summary>
  ''' Available physical memory.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property AvailablePhysicalMemory() As Long
    Get
      Return _availablePhysicalMemory
    End Get
    Set(ByVal value As Long)
      _availablePhysicalMemory = value
    End Set
  End Property
  Private _availableVirtualMemory As Long
  ''' <summary>
  ''' Available virtual memory.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property AvailableVirtualMemory() As Long
    Get
      Return _availableVirtualMemory
    End Get
    Set(ByVal value As Long)
      _availableVirtualMemory = value
    End Set
  End Property
  Private _totalPhysicalMemory As Long
  ''' <summary>
  ''' Total physical memory.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property TotalPhysicalMemory() As Long
    Get
      Return _totalPhysicalMemory
    End Get
    Set(ByVal value As Long)
      _totalPhysicalMemory = value
    End Set
  End Property
  Private _totalVirtualMemory As Long
  ''' <summary>
  ''' Total virtual memory.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property TotalVirtualMemory() As Long
    Get
      Return _totalVirtualMemory
    End Get
    Set(ByVal value As Long)
      _totalVirtualMemory = value
    End Set
  End Property
End Structure

''' <summary>
''' Computer information.
''' </summary>
''' <remarks></remarks>
Public Structure ComputerInfo
  Private _installedUICulture As String
  ''' <summary>
  ''' Installed UI culture.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property InstalledUICulture() As String
    Get
      Return _installedUICulture
    End Get
    Set(ByVal value As String)
      _installedUICulture = value
    End Set
  End Property
  Private _osFullName As String
  ''' <summary>
  ''' Operating system full name.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property OSFullName() As String
    Get
      Return _osFullName
    End Get
    Set(ByVal value As String)
      _osFullName = value
    End Set
  End Property
  Private _osPlatform As String
  ''' <summary>
  ''' Operating system platform.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property OSPlatform() As String
    Get
      Return _osPlatform
    End Get
    Set(ByVal value As String)
      _osPlatform = value
    End Set
  End Property
  Private _osVersion As String
  ''' <summary>
  ''' Operating system version.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property OSVersion() As String
    Get
      Return _osVersion
    End Get
    Set(ByVal value As String)
      _osVersion = value
    End Set
  End Property
End Structure

''' <summary>
''' Directory information.
''' </summary>
''' <remarks></remarks>
Public Structure DirectoryInformation
  Private _attributes As System.IO.FileAttributes
  ''' <summary>
  ''' Directory attributes.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Attributes() As System.IO.FileAttributes
    Get
      Return _attributes
    End Get
    Set(ByVal value As System.IO.FileAttributes)
      _attributes = value
    End Set
  End Property
  Private _creationTime As Date
  ''' <summary>
  ''' Directory createtion time.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property CreationTime() As Date
    Get
      Return _creationTime
    End Get
    Set(ByVal value As Date)
      _creationTime = value
    End Set
  End Property
  Private _fullName As String
  ''' <summary>
  ''' Directory full name.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property FullName() As String
    Get
      Return _fullName
    End Get
    Set(ByVal value As String)
      _fullName = value
    End Set
  End Property
  Private _lastAccessTime As Date
  ''' <summary>
  ''' Directory last access time.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property LastAccessTime() As Date
    Get
      Return _lastAccessTime
    End Get
    Set(ByVal value As Date)
      _lastAccessTime = value
    End Set
  End Property
  Private _lastWriteTime As Date
  ''' <summary>
  ''' Directory last write time.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property LastWriteTime() As Date
    Get
      Return _lastWriteTime
    End Get
    Set(ByVal value As Date)
      _lastWriteTime = value
    End Set
  End Property
  Private _name As String
  ''' <summary>
  ''' Directory name.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Name() As String
    Get
      Return _name
    End Get
    Set(ByVal value As String)
      _name = value
    End Set
  End Property
  Private _parentDirectory As String
  ''' <summary>
  ''' Parent directory.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property ParentDirectory() As String
    Get
      Return _parentDirectory
    End Get
    Set(ByVal value As String)
      _parentDirectory = value
    End Set
  End Property
  Private _root As String
  ''' <summary>
  ''' Root.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Root() As String
    Get
      Return _root
    End Get
    Set(ByVal value As String)
      _root = value
    End Set
  End Property
End Structure

''' <summary>
''' File information.
''' </summary>
''' <remarks></remarks>
Public Structure FileInformation
  Private _attributes As System.IO.FileAttributes
  ''' <summary>
  ''' File attributes.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Attributes() As System.IO.FileAttributes
    Get
      Return _attributes
    End Get
    Set(ByVal value As System.IO.FileAttributes)
      _attributes = value
    End Set
  End Property
  Private _creationTime As Date
  ''' <summary>
  ''' File creation time.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property CreationTime() As Date
    Get
      Return _creationTime
    End Get
    Set(ByVal value As Date)
      _creationTime = value
    End Set
  End Property
  Private _directoryName As String
  ''' <summary>
  ''' File directory name.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property DirectoryName() As String
    Get
      Return _directoryName
    End Get
    Set(ByVal value As String)
      _directoryName = value
    End Set
  End Property
  Private _extension As String
  ''' <summary>
  ''' File extention.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Extension() As String
    Get
      Return _extension
    End Get
    Set(ByVal value As String)
      _extension = value
    End Set
  End Property
  Private _fullName As String
  ''' <summary>
  ''' File full name.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property FullName() As String
    Get
      Return _fullName
    End Get
    Set(ByVal value As String)
      _fullName = value
    End Set
  End Property
  Private _isReadOnly As Boolean
  ''' <summary>
  ''' File is read only.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property IsReadOnly() As Boolean
    Get
      Return _isReadOnly
    End Get
    Set(ByVal value As Boolean)
      _isReadOnly = value
    End Set
  End Property
  Private _lastAccessTime As Date
  ''' <summary>
  ''' File last access time.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property LastAccessTime() As Date
    Get
      Return _lastAccessTime
    End Get
    Set(ByVal value As Date)
      _lastAccessTime = value
    End Set
  End Property
  Private _lastWriteTime As Date
  ''' <summary>
  ''' File last write time.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property LastWriteTime() As Date
    Get
      Return _lastWriteTime
    End Get
    Set(ByVal value As Date)
      _lastWriteTime = value
    End Set
  End Property
  Private _length As Long
  ''' <summary>
  ''' File length.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Length() As Long
    Get
      Return _length
    End Get
    Set(ByVal value As Long)
      _length = value
    End Set
  End Property
  Private _name As String
  ''' <summary>
  ''' File name.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Name() As String
    Get
      Return _name
    End Get
    Set(ByVal value As String)
      _name = value
    End Set
  End Property

  Public Overrides Function ToString() As String
    Return Me.FullName
  End Function

End Structure

''' <summary>
''' Device information.
''' </summary>
''' <remarks></remarks>
Public Structure DeviceInformation
  Private _caption As String
  ''' <summary>
  ''' Device caption.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Caption() As String
    Get
      Return _caption
    End Get
    Set(ByVal value As String)
      _caption = value
    End Set
  End Property
  Private _description As String
  ''' <summary>
  ''' File description.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Description() As String
    Get
      Return _description
    End Get
    Set(ByVal value As String)
      _description = value
    End Set
  End Property

  Public Overrides Function ToString() As String
    Return Me.Caption
  End Function

End Structure

''' <summary>
''' Server up time informaiton.
''' </summary>
''' <remarks></remarks>
Public Structure ServerUptimeInformation
  Private _bootTime As DateTime
  ''' <summary>
  ''' Boot time.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property BootTime() As DateTime
    Get
      Return _bootTime
    End Get
    Set(ByVal value As DateTime)
      _bootTime = value
    End Set
  End Property
  Private _currentTime As DateTime
  ''' <summary>
  ''' Current time.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property CurrentTime() As DateTime
    Get
      Return _currentTime
    End Get
    Set(ByVal value As DateTime)
      _currentTime = value
    End Set
  End Property
  Private _upTime As TimeSpan
  ''' <summary>
  ''' How long the computer has been running.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Uptime() As TimeSpan
    Get
      Return _upTime
    End Get
    Set(ByVal value As TimeSpan)
      _upTime = value
    End Set
  End Property

  Public Overrides Function ToString() As String
    Return Me.Uptime.ToString
  End Function

End Structure

''' <summary>
''' Installed product information.
''' </summary>
''' <remarks></remarks>
Public Structure InstalledProduct
  Private _caption As String
  ''' <summary>
  ''' Product caption.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Caption() As String
    Get
      Return _caption
    End Get
    Set(ByVal value As String)
      _caption = value
    End Set
  End Property
  Private _description As String
  ''' <summary>
  ''' Product description.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Description() As String
    Get
      Return _description
    End Get
    Set(ByVal value As String)
      _description = value
    End Set
  End Property
  Private _identifyingNumber As String
  ''' <summary>
  ''' Product identifying number.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property IdentifyingNumber() As String
    Get
      Return _identifyingNumber
    End Get
    Set(ByVal value As String)
      _identifyingNumber = value
    End Set
  End Property
  Private _installDate As Date
  ''' <summary>
  ''' Product installed date.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property InstallDate() As Date
    Get
      Return _installDate
    End Get
    Set(ByVal value As Date)
      _installDate = value
    End Set
  End Property
  Private _installLocation As String
  ''' <summary>
  ''' Product installed location.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property InstallLocation() As String
    Get
      Return _installLocation
    End Get
    Set(ByVal value As String)
      _installLocation = value
    End Set
  End Property
  Private _installState As Int32
  ''' <summary>
  ''' Product install state.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property InstallState() As Int32
    Get
      Return _installState
    End Get
    Set(ByVal value As Int32)
      _installState = value
    End Set
  End Property
  Private _installStateDescription As String
  ''' <summary>
  ''' Product install state description.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property InstallStateDescription() As String
    Get
      Return _installStateDescription
    End Get
    Set(ByVal value As String)
      _installStateDescription = value
    End Set
  End Property
  Private _name As String
  ''' <summary>
  ''' Product name.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Name() As String
    Get
      Return _name
    End Get
    Set(ByVal value As String)
      _name = value
    End Set
  End Property
  Private _packageCache As String
  ''' <summary>
  ''' Product package cache.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property PackageCache() As String
    Get
      Return _packageCache
    End Get
    Set(ByVal value As String)
      _packageCache = value
    End Set
  End Property
  Private _skuNumber As String
  ''' <summary>
  ''' Product SKU number.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property SkuNumber() As String
    Get
      Return _skuNumber
    End Get
    Set(ByVal value As String)
      _skuNumber = value
    End Set
  End Property
  Private _vendor As String
  ''' <summary>
  ''' Product vendor.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Vendor() As String
    Get
      Return _vendor
    End Get
    Set(ByVal value As String)
      _vendor = value
    End Set
  End Property
  Private _version As String
  ''' <summary>
  ''' Product version.
  ''' </summary>
  ''' <value></value>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Property Version() As String
    Get
      Return _version
    End Get
    Set(ByVal value As String)
      _version = value
    End Set
  End Property

  Public Overrides Function ToString() As String
    Return Me.Name
  End Function

End Structure
#End Region

''' <summary>
''' System information helper.
''' </summary>
''' <remarks></remarks>
Public NotInheritable Class ComputerHelper

  ''' <summary>
  ''' Product install state.
  ''' </summary>
  ''' <remarks></remarks>
  Private Enum ProductInstallState
    BadConfiguration = -6
    InvalidArgument = -2
    UnknownPackage = -1
    Advertised = 1
    Absent = 2
    Installed = 5
  End Enum

  ''' <summary>
  ''' Comptuer information for the current computer.
  ''' </summary>
  ''' <returns><seealso cref="ComputerInfo"/></returns>
  ''' <remarks></remarks>
  Public Shared Function ComputerInformation() As ComputerInfo

    Dim result As New ComputerInfo

    With result
      .InstalledUICulture = My.Computer.Info.InstalledUICulture.DisplayName
      .OSFullName = My.Computer.Info.OSFullName
      .OSPlatform = My.Computer.Info.OSPlatform
      .OSVersion = My.Computer.Info.OSVersion
    End With

    Return result

  End Function

  ''' <summary>
  ''' Current computer memory information.
  ''' </summary>
  ''' <returns><seealso cref="ComputerMemory"/></returns>
  ''' <remarks></remarks>
  Public Shared Function ComputerMemory() As ComputerMemory
    Dim result As New ComputerMemory

    With result
      If (Not Long.TryParse(My.Computer.Info.AvailablePhysicalMemory.ToString(CultureInfo.CurrentCulture), .AvailablePhysicalMemory)) Then
        .AvailablePhysicalMemory = 0
      End If

      If Not Long.TryParse(My.Computer.Info.AvailableVirtualMemory.ToString(CultureInfo.CurrentCulture), .AvailableVirtualMemory) Then
        .AvailableVirtualMemory = 0
      End If

      If Not Long.TryParse(My.Computer.Info.TotalPhysicalMemory.ToString(CultureInfo.CurrentCulture), .TotalPhysicalMemory) Then
        .TotalPhysicalMemory = 0
      End If

      If Not Long.TryParse(My.Computer.Info.TotalVirtualMemory.ToString(CultureInfo.CurrentCulture), .TotalVirtualMemory) Then
        .TotalVirtualMemory = 0
      End If
    End With

    Return result

  End Function

  ''' <summary>
  ''' Return drive info for the current drives on the system.
  ''' </summary>
  ''' <returns><seealso cref="System.IO.DriveInfo"/></returns>
  ''' <remarks></remarks>
  Public Shared Function ComputerReadyDrives() As System.Collections.ObjectModel.ReadOnlyCollection(Of System.IO.DriveInfo)
    Dim drives As New System.Collections.Generic.List(Of System.IO.DriveInfo)

    For Each drive As System.IO.DriveInfo In My.Computer.FileSystem.Drives
      If drive.IsReady Then
        drives.Add(drive)
      End If
    Next

    Return New System.Collections.ObjectModel.ReadOnlyCollection(Of System.IO.DriveInfo)(drives)

  End Function

  ''' <summary>
  ''' Current computer time.
  ''' </summary>
  ''' <returns><seealso cref="DateTime"/></returns>
  ''' <remarks></remarks>
  Public Shared Function CurrentTime() As DateTime

    Return My.Computer.Clock.LocalTime

  End Function

  ''' <summary>
  ''' Fines user domain and name.
  ''' </summary>
  ''' <returns>User domain and name.</returns>
  ''' <remarks></remarks>
  Shared Function LookupUserNameDomain() As String
    Return String.Format(CultureInfo.CurrentCulture, "{0}\{1}", System.Environment.UserDomainName, System.Environment.UserName)
  End Function



  ''' <summary>
  ''' Finds the server up time.
  ''' </summary>
  ''' <param name="machineNameOrAddress">Machine name or address.</param>
  ''' <returns><seealso cref="ServerUpTimeInformation"/></returns>
  ''' <remarks></remarks>
  Public Shared Function ServerUptime(ByVal machineNameOrAddress As String) As ServerUptimeInformation
    Dim result As New ServerUptimeInformation
    Dim options As New ConnectionOptions()
    Dim scope As ManagementScope

    'default to the local system
    Dim system As String = machineNameOrAddress

    Dim path As String = String.Format(CultureInfo.CurrentCulture, "\\{0}\root\CIMV2", system)
    scope = New ManagementScope(path, options)

    'query the management scope for the instance(s) of the operating system
    'management object
    Using searcher As New ManagementObjectSearcher(scope, New ObjectQuery("SELECT LocalDateTime, LastBootUpTime FROM CIM_OperatingSystem"))

      Using searchResults As ManagementObjectCollection = searcher.Get()

        'foreach is a the wrong iterative structure since there would never be more than one object
        For Each management As ManagementObject In searchResults
          'get the time for the last successfull bootup of the machine, and calculate the time diff
          result.CurrentTime = ConvertWMIDateTime(CStr(management.GetPropertyValue("LocalDateTime")))
          result.BootTime = ConvertWMIDateTime(CStr(management.GetPropertyValue("LastBootUpTime")))

          Dim span As TimeSpan = result.CurrentTime.Subtract(result.BootTime)

          result.Uptime = span

        Next
      End Using

    End Using

    Return result

  End Function

  '/ <param name="value">a datetime string in the WMI format</param>
  '/ <returns>a DateTime object converted from the WMI datetime string</returns>
  Private Shared Function ConvertWMIDateTime(ByVal value As String) As System.DateTime
    Dim year As Int32 = System.DateTime.Now.Year
    Dim month As Int32 = 1
    Dim day As Int32 = 1
    Dim hour As Int32 = 0
    Dim minute As Int32 = 0
    Dim second As Int32 = 0
    Dim millisecond As Int32 = 0
    Dim tempString As String = System.String.Empty

    If System.String.IsNullOrEmpty(value) Then
      Return System.DateTime.MinValue
    End If

    '8 character date
    tempString = value.Substring(0, 4)
    If "****" <> tempString Then
      year = System.Int32.Parse(tempString, CultureInfo.CurrentCulture)
    End If
    tempString = value.Substring(4, 2)
    If "**" <> tempString Then
      month = System.Int32.Parse(tempString, CultureInfo.CurrentCulture)
    End If
    tempString = value.Substring(6, 2)
    If "**" <> tempString Then
      day = System.Int32.Parse(tempString, CultureInfo.CurrentCulture)
    End If

    '25 character date/time
    If value.Length > 8 Then

      tempString = value.Substring(8, 2)
      If "**" <> tempString Then
        hour = System.Int32.Parse(tempString, CultureInfo.CurrentCulture)
      End If
      tempString = value.Substring(10, 2)
      If "**" <> tempString Then
        minute = System.Int32.Parse(tempString, CultureInfo.CurrentCulture)
      End If
      tempString = value.Substring(12, 2)
      If "**" <> tempString Then
        second = System.Int32.Parse(tempString, CultureInfo.CurrentCulture)
      End If
      tempString = value.Substring(15, 3)
      If "***" <> tempString Then
        millisecond = System.Int32.Parse(tempString, CultureInfo.CurrentCulture)
      End If

    End If

    Return New System.DateTime(year, month, day, hour, minute, second, millisecond)

  End Function 'ToDateTime

  ''' <summary>
  ''' Finds devices attached to the computer.
  ''' </summary>
  ''' <param name="machineNameOrAddress">Machine name or address.</param>
  ''' <returns>Collection of <seealso cref="DeviceInformation"/></returns>
  ''' <remarks>This call could take some time. Recommend multi-threading.</remarks>
  Public Shared Function ServerDevices(ByVal machineNameOrAddress As String) As System.Collections.ObjectModel.ReadOnlyCollection(Of DeviceInformation)
    Dim options As New ConnectionOptions()
    Dim scope As ManagementScope
    Dim devices As New System.Collections.Generic.List(Of DeviceInformation)

    'default to the local system
    Dim system As String = machineNameOrAddress

    Dim path As String = String.Format(CultureInfo.CurrentCulture, "\\{0}\root\CIMV2", system)
    scope = New ManagementScope(path, options)

    'query the management scope for the instance(s) of the operating system
    'management object

    Using searcher As New ManagementObjectSearcher(scope, New ObjectQuery("SELECT Caption,Description FROM CIM_LogicalDevice"))

      Using searchResults As ManagementObjectCollection = searcher.Get()

        'foreach is a the wrong iterative structure since there would never be more than one object
        For Each management As ManagementObject In searchResults
          'get the time for the last successfull bootup of the machine, and calculate the time diff
          Dim device As New DeviceInformation
          device.Caption = CStr(management.GetPropertyValue("Caption"))
          device.Description = CStr(management.GetPropertyValue("Description"))
          devices.Add(device)
        Next

      End Using

    End Using

    Return New System.Collections.ObjectModel.ReadOnlyCollection(Of DeviceInformation)(devices)

  End Function

  ''' <summary>
  ''' Finds software installed on a computer.
  ''' </summary>
  ''' <param name="machineNameOrAddress">Machine name or address.</param>
  ''' <returns>Colleciton of <seealso cref="InstalledProduct"/></returns>
  ''' <remarks>This call could take some time. Recommend multi-threading.</remarks>
  Public Shared Function ServerInstalledSoftware(ByVal machineNameOrAddress As String) As System.Collections.ObjectModel.ReadOnlyCollection(Of InstalledProduct)

    Dim result As New System.Collections.Generic.List(Of InstalledProduct)

    Using searcher As New ManagementObjectSearcher(String.Format(CultureInfo.CurrentCulture, "\\{0}\root\CIMV2", machineNameOrAddress), "SELECT Caption, Description, IdentifyingNumber, InstallDate, InstallLocation, InstallState, Name, PackageCache, SKUNumber, Vendor, Version FROM Win32_Product")

      For Each queryObj As ManagementObject In searcher.Get

        If Not IsNothing(queryObj) Then
          Dim product As New InstalledProduct

          With product
            If Not IsNothing(queryObj("Caption")) Then
              .Caption = queryObj("Caption").ToString
            End If
            If Not IsNothing(queryObj("Description")) Then
              .Description = queryObj("Description").ToString
            End If
            If Not IsNothing(queryObj("IdentifyingNumber")) Then
              .IdentifyingNumber = queryObj("IdentifyingNumber").ToString
            End If

            .InstallDate = ConvertWMIDateTime(queryObj("InstallDate").ToString)

            If Not IsNothing(queryObj("InstallLocation")) Then
              .InstallLocation = queryObj("InstallLocation").ToString
            End If

            If Not Int32.TryParse(queryObj("InstallState").ToString, .InstallState) Then
              'Default to Unknown
              .InstallState = ProductInstallState.UnknownPackage
            End If

            If System.Enum.IsDefined(GetType(ProductInstallState), .InstallState) Then
              .InstallStateDescription = System.Enum.GetName(GetType(ProductInstallState), .InstallState).ToString
            End If

            If Not IsNothing(queryObj("Name")) Then
              .Name = queryObj("Name").ToString
            End If

            If Not IsNothing(queryObj("PackageCache")) Then
              .PackageCache = queryObj("PackageCache").ToString
            End If

            If Not IsNothing(queryObj("SKUNumber")) Then
              .SkuNumber = queryObj("SKUNumber").ToString
            End If

            If Not IsNothing(queryObj("Vendor")) Then
              .Vendor = queryObj("Vendor").ToString
            End If

            If Not IsNothing(queryObj("Version")) Then
              .Version = queryObj("Version").ToString
            End If

          End With

          result.Add(product)

        End If
      Next
    
    End Using

    Return New System.Collections.ObjectModel.ReadOnlyCollection(Of InstalledProduct)(result)

  End Function


  ''' <summary>
  ''' Relases DHCP for the current computer.
  ''' </summary>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function ReleaseDhcpLease() As Int32
    Dim result As Int32

    Using classInstance As New ManagementClass("root\CIMV2", "Win32_NetworkAdapterConfiguration", Nothing)

      ' Execute the method and obtain the return values.
      Using outParams As ManagementBaseObject = classInstance.InvokeMethod("ReleaseDHCPLeaseAll", Nothing, Nothing)

        If Not Int32.TryParse(outParams("result").ToString, result) Then
          result = -1
        End If

      End Using
    End Using

    Return result

  End Function

  ''' <summary>
  ''' Renews DHCP for the current computer.
  ''' </summary>
  ''' <returns></returns>
  ''' <remarks></remarks>
  Public Shared Function RenewDhcpLease() As Int32
    Dim result As Int32

    Using classInstance As New ManagementClass("root\CIMV2", "Win32_NetworkAdapterConfiguration", Nothing)

      ' Execute the method and obtain the return values.
      Using outParams As ManagementBaseObject = classInstance.InvokeMethod("RenewDHCPLeaseAll", Nothing, Nothing)

        If Not Int32.TryParse(outParams("result").ToString, result) Then
          result = -1
        End If

      End Using
    End Using

    Return result

  End Function

  Private Sub New()
  End Sub
End Class
